package dataset;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


/**
 * Represents a DataSet to be graphed.
 *
 * @author Paul Dannenberg
 * @author Mark Hoffman
 *
 */

public class DataSet {

    private Collection<DataPoint> myDataSet;
    private String myTitle;

    /**
     *
     * @param data
     * @param title
     */
    public DataSet (Collection<DataPoint> data, String title) {
        myDataSet = data;
        myTitle = title;
    }

    /**
     * Filters out all coordinates that lie outside particular
     * bounds. Acts on x coordinates.
     *
     * @param lowerBound Lowest value to be accepted
     * @param upperBound Largest value to be accepted
     */
    public void filterX (double lowerBound, double upperBound) {
        for (DataPoint point : myDataSet) {
            if (point.getX() < lowerBound || point.getX() > upperBound) {
                myDataSet.remove(point);
            }
        }
    }

    /**
     * Filters out coordinates that lie outside a particular
     * bounds. Acts on y coordinates.
     *
     * @param lowerBound Lowest value to be accepted
     * @param upperBound Largest Value to be accepted
     */
    public void filterY (double lowerBound, double upperBound) {
        for (DataPoint point : myDataSet) {
            if (point.getY() < lowerBound || point.getY() > upperBound) {
                myDataSet.remove(point);
            }
        }
    }

    /**
     * Finds the largest y value.
     *
     * @return
     */
    public double getMaxY () {
        double largest = getFirstPoint().getY();
        for (DataPoint point : myDataSet) {
            if(point.getY() > largest) {
                largest = point.getY();
            }
        }
        return largest;
    }

    /**
     * Finds the smallest y value.
     *
     * @return
     */
    public double getMinY () {
        double smallest = getFirstPoint().getY();
        for (DataPoint point : myDataSet) {
            if(point.getY() < smallest) {
                smallest = point.getY();
            }
        }
        return smallest;
    }
    
    /**
     * Finds the largest x value.
     *
     * @return
     */
    public double getMaxX () {
        double largest = getFirstPoint().getX();
        for (DataPoint point : myDataSet) {
            if(point.getX() > largest) {
                largest = point.getX();
            }
        }
        return largest;
    }

    /**
     * Finds the smallest x value.
     *
     * @return
     */
    public double getMinX () {
        double smallest = getFirstPoint().getX();
        for (DataPoint point : myDataSet) {
            if(point.getX() < smallest) {
                smallest = point.getX();
            }
        }
        return smallest;
    }


    /**
     *
     * @param toMerge a map of data to be added to the current map
     */
    public void merge (Collection<DataPoint> toMerge) {
        myDataSet.addAll(toMerge);
    }

    /**
     * Computes the mean of the x coordinates.
     *
     * @return
     */
    public double averageX () {
        double total = 0;
        int counter = 0;
        for (DataPoint point : myDataSet) {
            total += point.getX();
            counter++;
        }
        return total/counter;
    }

    /**
     * Computes the mean of the y coordinates.
     *
     * @return
     */
    public double averageY () {
        double total = 0;
        int counter = 0;
        for (DataPoint point : myDataSet) {
            total += point.getY();
            counter++;
        }
        return total/counter;
    }

    /**
     * Returns a best fit line for the data, based
     * on a linear fit.
     *
     * @return
     */
    public DataSet fit () {
        return null;
    }

    /**
     * Removes all outliers that are above a certain
     * y distance away from the line of best fit.
     *
     * @param threshold A y distance away from the
     *        line of best fit. Coordinates at a distance
     *        greate than theshold from the line of best fit
     *        will be removed from the dataset.
     */
    public void removeOutliers (double threshold) {
        
    }
    
    public String getTitle() {
        return myTitle;
    }

    public Collection<DataPoint> getData () {
        return myDataSet;
    }
    
    private DataPoint getFirstPoint() {
        for (DataPoint point : myDataSet) {
            return point;
        }
        return null;
    }
}
